import { SquareGroup } from "./SquareGroup";
import { EMoveDirection, IPoint, TShape } from "./types";
import Configs from "@/config";

export function isPoint(obj: any): obj is IPoint {
  return (
    obj.x !== undefined &&
    obj.y !== undefined &&
    typeof obj.x === "number" &&
    typeof obj.y === "number"
  );
}
/**
 * 该类中提供了俄罗斯方块的规则
 */
export class TerisRule {
  /**
   * @param shape 形状
   * @param targetPoint 中心点的位置
   */
  static canIMove(shape: TShape, targetPoint: IPoint) {
    // 边界检测
    const targetSquarePoints = shape.map((p) => ({
      x: p.x + targetPoint.x,
      y: p.y + targetPoint.y,
    }));
    const isCanMove = targetSquarePoints.some((p) => {
      // 是否超出边界
      return (
        p.x < 0 ||
        p.x >= Configs.panelWidth ||
        p.y < 0 ||
        p.y >= Configs.panelHeight
      );
    });
    return !isCanMove;
  }

  static move(SquareGroup: SquareGroup, targetPoint: IPoint): boolean;
  static move(SquareGroup: SquareGroup, direction: EMoveDirection): boolean;
  static move(
    SquareGroup: SquareGroup,
    targetPointOrDirec: IPoint | EMoveDirection
  ) {
    if (isPoint(targetPointOrDirec)) {
      if (this.canIMove(SquareGroup.shape, targetPointOrDirec)) {
        SquareGroup.centerPointMove(targetPointOrDirec);
        return true;
      } else {
        return false;
      }
    } else {
      let targetPoint: IPoint;
      if (targetPointOrDirec === EMoveDirection.down) {
        targetPoint = {
          x: SquareGroup.centerPoint.x,
          y: SquareGroup.centerPoint.y + 1,
        };
      } else {
        targetPoint = {
          x:
            targetPointOrDirec === EMoveDirection.left
              ? SquareGroup.centerPoint.x - 1
              : SquareGroup.centerPoint.x + 1,
          y: SquareGroup.centerPoint.y,
        };
      }
      return this.move(SquareGroup, targetPoint);
    }
  }

  static moveDirectly(SquareGroup: SquareGroup, direction: EMoveDirection) {
    while (this.move(SquareGroup, direction)) {}
  }

  static rotate(SquareGroup: SquareGroup) {
    const newShape = SquareGroup.afterRotateShape();
    if (this.canIMove(newShape, SquareGroup.centerPoint)) {
      SquareGroup.rotate();
      return true;
    } else {
      return false;
    }
  }
}
